package com.longsong.ad_pedometer;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;
import com.longsong.ad_pedometer.databinding.ActivityMainBinding;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {
    private boolean isBind;
    private static MqttAndroidClient mqttAndroidClient;
    private int totalStepNum = 10000;
    private int yesterdayStep;
    private int temp = 0;
    private ActivityMainBinding mViewBinding;
    private StepService stepService;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                getDayOfWeek();
                updateWeekChange();
//                int updateData  = msg.arg1-temp;
//                temp = msg.arg1;
//                databaseHelper.updateSteps(week,updateData);
                setData();
                mViewBinding.mBarChart.invalidate();
                mViewBinding.yesStepNum.setText(databaseHelper.getSteps(yesterdayStep) + " 步");
                mViewBinding.totalStepNum.setText(databaseHelper.getTotalSteps() + " 步");
                mViewBinding.stepProcess.setCurrentCount(totalStepNum,databaseHelper.getSteps(week));
                ifDayChange();
                saveOpenDay();
            }
        }
    };
    private StepDBSQLiteHelper databaseHelper;
    private SQLiteDatabase db;
    private  int week;


//获取权限
//    private void getoperation() {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
//            Log.d("TAG", "[权限]" + "ACTIVITY_RECOGNITION 未获得");
//            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED) {
//                // 检查权限状态
//                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACTIVITY_RECOGNITION)) {
//                    //  用户彻底拒绝授予权限，一般会提示用户进入设置权限界面
//                    Log.d("TAG", "[权限]" + "ACTIVITY_RECOGNITION 以拒绝，需要进入设置权限界面打开");
//                } else {
//                    //  用户未彻底拒绝授予权限
//                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, 1);
//                    Log.d("TAG", "[权限]" + "ACTIVITY_RECOGNITION 未彻底拒绝拒绝，请求用户同意");
//                }
////                return;
//            }else{
//
//                Log.d("TAG", "[权限]" + "ACTIVITY_RECOGNITION ready");
//            }
//        }else{
//
//        }
//
//    }
//
//    @Override
//    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
//        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//        if (requestCode == 1) {
//            for (int i = 0; i < permissions.length; i++) {
//                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
//                    // 申请成功
//                    Log.d("TAG", "[权限]" + "ACTIVITY_RECOGNITION 申请成功");
//                } else {
//                    // 申请失败
//                    Log.d("TAG", "[权限]" + "ACTIVITY_RECOGNITION 申请失败");
//                }
//            }
//        }
//
//    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //ViewBinding绑定
        mViewBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(mViewBinding.getRoot());

        //数据库操作
        databaseHelper = new StepDBSQLiteHelper(this);
        db = databaseHelper.getWritableDatabase();
        databaseHelper.onCreate(db);
        databaseHelper.initTable();
        //获得当天星期
        getDayOfWeek();
        //当星期变更
        updateWeekChange();
        //当日期变更
        ifDayChange();
        //保存今天
        saveOpenDay();
        //初始化视图
        mViewBinding.stepProcess.setCurrentCount(totalStepNum,databaseHelper.getSteps(week));
        mViewBinding.yesStepNum.setText(databaseHelper.getSteps(yesterdayStep) + " 步");
        mViewBinding.totalStepNum.setText(databaseHelper.getTotalSteps() + " 步");
        //柱状图
        initBarChart();

        Intent intent = new Intent(MainActivity.this,StepService.class);
        isBind = bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);
//        this.getoperation();
        startService(intent);
    }

    private void ifDayChange(){
        SharedPreferences sp = getSharedPreferences("time", Context.MODE_PRIVATE);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String today = dateFormat.format(new Date());
        String lastOpenDay = sp.getString("openDate", null);


        Log.i("ifDayChange()","->today: "+today);

        //System.out.println("getOpenDay:"+lastOpenDay);
        if (lastOpenDay==null){
            return ;
        }
        if (today.equals(lastOpenDay)){
            Log.i("ifDayChange()","->lastOpenDay: "+lastOpenDay);
            Log.i("ifDayChange","今天是同一天");
            return ;
        }else {
            Log.i("ifDayChange","今天不是同一天,开启mqtt");
             mqttPub(databaseHelper.getPayload());
             return;
        }
    }

    private void mqttPub(String payload){
        String host = "tcp://122.224.240.66:1883";
        String clientId = UUID.randomUUID().toString().replaceAll("-","");
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setConnectionTimeout(3);//3秒连不上断线

        /* 创建MqttAndroidClient对象，并设置回调接口。 */
        mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);

        try {
            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Toast.makeText(MainActivity.this,"连接成功!",Toast.LENGTH_SHORT).show();

                    String topic = "TodayStep";

                    try {
                        MqttMessage message = new MqttMessage();
                        message.setPayload(payload.getBytes());
                        message.setQos(0);
                        mqttAndroidClient.publish(topic, message, null, new IMqttActionListener() {
                            @Override
                            public void onSuccess(IMqttToken asyncActionToken) {
                                Toast.makeText(MainActivity.this,"发布成功！",Toast.LENGTH_LONG).show();
                                try {
                                    if (mqttAndroidClient!=null){
                                        mqttAndroidClient.disconnect();
                                    }
                                } catch (MqttException e) {
                                    e.printStackTrace();
                                }finally {
                                    mqttAndroidClient = null;
                                }
                            }

                            @Override
                            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {

                                String msg = "";
                                if (exception != null) {
                                    msg = "," + exception.getMessage();
                                    exception.printStackTrace();
                                } else {
                                    msg = "，未知错误！";
                                }
                                Toast.makeText(MainActivity.this,"发布失败！"+msg,Toast.LENGTH_SHORT).show();
                            }
                        });
                    } catch (MqttException e) {
                        String msg = "";
                        if (e != null) {
                            msg = "," + e.getMessage();
                            e.printStackTrace();
                        } else {
                            msg = "未知错误！";
                        }
                        Toast.makeText(MainActivity.this,"发布失败！"+msg,Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Toast.makeText(MainActivity.this,"连接失败!",Toast.LENGTH_LONG).show();
                    exception.printStackTrace();
                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }


        mqttAndroidClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                Toast.makeText(MainActivity.this,"连接掉线!",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {

            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                Toast.makeText(MainActivity.this,"发送成功!",Toast.LENGTH_SHORT).show();
            }
        });
    }


    private void saveOpenDay(){
        SharedPreferences sp = getSharedPreferences("time", Context.MODE_PRIVATE);
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String openDay = dateFormat.format(date);
        if(sp.getString("openDate",null)!=openDay){
            sp.edit().putString("openDate", openDay).commit();
        }
        //System.out.println("saveOpenDate:"+openDate);
    }

    private void updateWeekChange(){
        try {
            if (isSameWeekWithToday()) {
                Log.i("updateWeekChange:","今天是同一星期");
            } else {
                Log.i("updateWeekChange:","今天不是同一星期");
                databaseHelper.initWeekSteps(week);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //saveOpenDay();
    }

    private void getDayOfWeek(){
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        int todayWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (todayWeek == 1){
            week = 7;
        }else {
            week = todayWeek-1;
        }

        if (week==1){
            yesterdayStep = 7;
        }else {
            yesterdayStep = week-1;
        }
        Log.i("getDayOfWeek","week: "+week+"yesterday: "+yesterdayStep);
    }

    /**
     * 判断date和当前日期是否在同一周内
     * 注:
     * Calendar类提供了一个获取日期在所属年份中是第几周的方法，对于上一年末的某一天
     * 和新年初的某一天在同一周内也一样可以处理，例如2012-12-31和2013-01-01虽然在
     * 不同的年份中，但是使用此方法依然判断二者属于同一周内
     */
    private boolean isSameWeekWithToday() throws ParseException {

        SharedPreferences sp = getSharedPreferences("time", Context.MODE_PRIVATE);
        Date LastOpenDate = null;
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String lastOpenDay = sp.getString("openDate", null);
        //System.out.println("getOpenDay:"+lastOpenDay);


        if (lastOpenDay!=null){
           LastOpenDate = dateFormat.parse(lastOpenDay);
           Log.i("lastOpenDay",lastOpenDay);
        }


        if (LastOpenDate == null) {
            return false;
        }

        // 0.先把Date类型的对象转换Calendar类型的对象
        Calendar todayCal = Calendar.getInstance();
        Calendar dateCal = Calendar.getInstance();

        todayCal.setTime(new Date());
        dateCal.setTime(LastOpenDate);

        // 1.比较当前日期在年份中的周数是否相同
        if (todayCal.get(Calendar.WEEK_OF_YEAR) == dateCal.get(Calendar.WEEK_OF_YEAR)) {
            return true;
        } else {
            return false;
        }
    }

    private void initBarChart() {
        mViewBinding.mBarChart.getDescription().setEnabled(false); // 不显示描述
        mViewBinding.mBarChart.setExtraOffsets(20, 20, 20, 20); // 设置饼图的偏移量，类似于内边距 ，设置视图窗口大小
        setAxis(); // 设置坐标轴
        mViewBinding.mBarChart.getLegend().setEnabled(false); // 设置图例不显示
        setData();  // 设置数据
    }

    /**
     * 因为此处的 barData.setBarWidth(0.3f);，也就是说柱子的宽度是0.3f
     * 所以第二个柱子的值要比第一个柱子的值多0.3f，这样才会并列显示两根柱子
     */
    private void setData() {
        // 此处有两个DataSet，所以有两条柱子，BarEntry（）中的x和y分别表示显示的位置和高度
        // x是横坐标，表示位置，y是纵坐标，表示高度

        List<BarEntry> allStepData = databaseHelper.getAllStepData();
        BarDataSet barDataSet = new BarDataSet(allStepData, "");
        barDataSet.setValueTextColor(Color.RED); // 值的颜色
        barDataSet.setValueTextSize(10f); // 值的大小
        barDataSet.setColor(Color.parseColor("#1AE61A")); // 柱子的颜色
        //barDataSet1.setLabel("蔬菜"); // 设置标签之后，图例的内容默认会以设置的标签显示
        // 设置柱子上数据显示的格式
        barDataSet.setValueFormatter(new IValueFormatter() {
            @Override
            public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
                // 此处的value默认保存一位小数
                return (int)value + "步";
            }
        });


        BarData barData = new BarData(barDataSet);
        barData.setBarWidth(0.5f); // 设置柱子的宽度
        mViewBinding.mBarChart.setData(barData);
    }


    private void setAxis() {
        // 设置x轴
        XAxis xAxis = mViewBinding.mBarChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);  // 设置x轴显示在下方，默认在上方
        xAxis.setDrawGridLines(false); // 将此设置为true，绘制该轴的网格线。
        xAxis.setLabelCount(7);  // 设置x轴上的标签个数
        xAxis.setTextSize(15f); // x轴上标签的大小
        final String labelName[] = {"周一", "周二", "周三", "周四", "周五","周六","周日"};
        // 设置x轴显示的值的格式
        xAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                if ((int) value <= labelName.length) {
                    return labelName[(int) value-1];
                } else {
                    return "";
                }
            }
        });
        xAxis.setYOffset(15); // 设置标签对x轴的偏移量，垂直方向

        // 设置y轴，y轴有两条，分别为左和右
        YAxis yAxis_right = mViewBinding.mBarChart.getAxisRight();
        yAxis_right.setAxisMaximum(10000f);  // 设置y轴的最大值
        yAxis_right.setAxisMinimum(0f);  // 设置y轴的最小值
        yAxis_right.setEnabled(false);  // 不显示右边的y轴

        YAxis yAxis_left = mViewBinding.mBarChart.getAxisLeft();
        yAxis_left.setAxisMaximum(10000f);
        yAxis_left.setAxisMinimum(0f);
        yAxis_left.setEnabled(false);  // 不显示左边的y轴
//        yAxis_left.setTextSize(15f); // 设置y轴的标签大小
    }


    //app被关闭之前，service先解除绑定，
    // 如果不解除绑定下次Activity切换到活动界面的时候又会重新开启一个新的计步线程。
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isBind) {
            this.unbindService(serviceConnection);
        }
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            StepService.LcBinder lcBinder = (StepService.LcBinder) service;
            stepService = lcBinder.getService();
            stepService.registerCallback( new UpdateUiCallBack() {
                @Override
                public void updateUi(int stepCount) {
                    Message message = Message.obtain();
                    message.what = 1;
                    message.arg1 = stepCount;
                    handler.sendMessage(message);
                    Log.i("MainActivity—updateUi","当前步数"+stepCount);
                }
            });

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.i("MainActivity—updateUi","连接断开");
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("onResume","onResume了");
        //获得当天星期
        getDayOfWeek();
        //当日期变更
        ifDayChange();
        //当星期变更
        updateWeekChange();
        //保存今天
        saveOpenDay();
        //初始化视图
        mViewBinding.stepProcess.setCurrentCount(totalStepNum,databaseHelper.getSteps(week));
        mViewBinding.yesStepNum.setText(databaseHelper.getSteps(yesterdayStep) + " 步");
        mViewBinding.totalStepNum.setText(databaseHelper.getTotalSteps() + " 步");
    }
}